package com.yfyszk.kingbird.aspect;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.yfyszk.kingbird.annotation.FormLock;
import com.yfyszk.kingbird.exception.GlobalServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 防止表单重复提交
 * @since on 2020/08/10.
 */
@Slf4j
public class FormAspect extends  AbstractAspectManager{
    private static final Cache<String, Object> CACHES = CacheBuilder.newBuilder()
            // 最大缓存 100 个
            .maximumSize(1000)
            // 设置写缓存后 60 秒过期
            .expireAfterWrite(60, TimeUnit.SECONDS)
            .build();

    public FormAspect(AspectApi aspectApi){
        super(aspectApi);
    }


    @Override
    public Object doHandlerAspect(ProceedingJoinPoint pjp, Method method) throws Throwable {
        super.doHandlerAspect(pjp,method);
        execute(pjp,method);
        return null;
    }

    @Override
    protected Object execute(ProceedingJoinPoint pjp, Method method)throws Throwable{
        //防止表单重复提交
        FormLock formLock = method.getAnnotation(FormLock.class);
        if (formLock != null) {
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
            HttpServletRequest request = sra.getRequest();
            String authorization = request.getHeader("token");
            String key = getKey(request, method, authorization);
            log.info("key:{}", key);
            if (!StringUtils.isEmpty(key)) {
                if (CACHES.getIfPresent(key) != null) {
                    throw new GlobalServiceException(1, "请勿重复提交");
                }
                // 如果是第一次请求,就将 key 当前对象压入缓存中
                CACHES.put(key, key);
            }
        }
        return null;
    }
    /**
     * 获取getKey
     *
     * @param request
     * @param method
     * @return
     */
    private String getKey(HttpServletRequest request, Method method, String userId) {
        StringBuffer sb = new StringBuffer();
        String requestURI = request.getRequestURI();
        // 拼接请求路径
        sb.append(requestURI);
        // 拼接目标方法名称
        sb.append(method.getName());
        sb.append(userId);
        Map<String, String[]> parameterMap = request.getParameterMap();
        if (parameterMap != null) {
            Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
            if (entries != null) {
                for (Map.Entry<String, String[]> entry : entries) {
                    sb.append(entry.getKey()).append(Arrays.toString(entry.getValue()));
                }
            }
        }
        return sb.toString();
    }
}
